package cn.kent.heima.high.garbage;

import java.util.ArrayList;

/**
 * -Xms20m -Xmx20m -Xmn10m -XX:+UseSerialGC -XX:+PrintGCDetails -verbose:gc
 *
 * 看gc打印的内容，然后代码执行放入内存，观察jvm内存变化
 * 1. 为什么新生代只有9M, 实际参数指定的是-Xmn10m? -> 因为to幸存区分了1M, 这个被认为是不能被使用的, 没毛病, 实际能用的只有9M
 *
 * Heap
 *  新生代-> def new generation   total 9216K, used 2010K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
 *      伊甸园->    eden space 8192K,  24% used [0x00000000fec00000, 0x00000000fedf6938, 0x00000000ff400000)
 *      from幸存区-> from space 1024K,   0% used [0x00000000ff400000, 0x00000000ff400000, 0x00000000ff500000)
 *      to幸存区->   to   space 1024K,   0% used [0x00000000ff500000, 0x00000000ff500000, 0x00000000ff600000)
 *  晋升的老年代/老年代-> tenured generation   total 10240K, used 0K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
 *    the space 10240K,   0% used [0x00000000ff600000, 0x00000000ff600000, 0x00000000ff600200, 0x0000000100000000)
 *  元空间-> Metaspace       used 3189K, capacity 4496K, committed 4864K, reserved 1056768K
 *   class space    used 349K, capacity 388K, committed 512K, reserved 1048576K
 */
public class Demo_17 {
    private static final int _512KB = 512 * 1024;
    private static final int _1MB = 1024 * 1024;
    private static final int _6MB = 6 * 1024 * 1024;
    private static final int _7MB = 7 * 1024 * 1024;
    private static final int _8MB = 8 * 1024 * 1024;

    public static void main(String[] args) throws InterruptedException {

//        ArrayList<byte[]> list = new ArrayList<>();
//        // 触发一次新生代gc
//        //      不可回收              新生代:   原剩余大小 -> 新剩余大小(总大小), 耗时         堆的总容量变化,
//        // [GC (Allocation Failure) [DefNew: 1846K->617K(9216K), 0.0009704 secs] 1846K->617K(19456K), 0.0010011 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
//        list.add(new byte[_7MB]);
//        list.add(new byte[_512KB]); // 足够放下, 可以直接放入新生代
//        list.add(new byte[_512KB]); // 放不下了, 再触发一次新生代gc


//        // 演示: 大对象直接晋升到老年代
//        ArrayList<byte[]> list = new ArrayList<>();
//        list.add(new byte[_8MB]); // 8M超过伊甸园的总容量, 直接到老年代
//        list.add(new byte[_8MB]); // 新生代和老年代都放不下这么大对象了, 抛出error->OOM

        // 注意: 线程内的oom不会导致主线程结束
        new Thread(new Runnable() {
            @Override
            public void run() {
                ArrayList<byte[]> list = new ArrayList<>();
                list.add(new byte[_8MB]);
                list.add(new byte[_8MB]);
            }
        }).start();
        System.out.println("sleep...");
        Thread.sleep(1000);
    }
}
